﻿#ifndef JZ_PROPERTY_EDITOR_H_
#define JZ_PROPERTY_EDITOR_H_

#include <QWidget>
#include <QSharedPointer>
#include "JZPropertyBrowser.h"

class PropVistior
{
public:
    virtual void setValue(const QVariant &v) = 0;
    virtual QVariant value() = 0;
};
typedef QSharedPointer<PropVistior> PropVistiorPtr;

template<class T>
class PropVistiorImpl : public PropVistior
{
public:
    PropVistiorImpl(T *p)
    {
        ptr = p;
    }

    virtual void setValue(const QVariant &v) override
    {
        *ptr = v.value<T>();
    }

    virtual QVariant value() override
    {
        return QVariant::fromValue<T>(*ptr);
    }

    T *ptr;
};

template<class T>
class PropVistiorEnumImpl : public PropVistior
{
public:
    PropVistiorEnumImpl(T *p)
    {
        ptr = p;
    }

    virtual void setValue(const QVariant &v) override
    {
        *ptr = (T)v.value<int>();
    }

    virtual QVariant value() override
    {
        return QVariant::fromValue<int>((int)*ptr);
    }

    T *ptr;
};

class JZPropertyEditor : public QWidget
{
    Q_OBJECT

public:
    JZPropertyEditor(QWidget *widget = nullptr);
    ~JZPropertyEditor(); 

    JZPropertyBrowser *browser();
    JZProperty *addGroup(QString name);     
    
    template<class T>
    JZProperty *addProp(QString name, T *ptr, JZProperty *parent = nullptr)
    {
        PropVistiorPtr vistor = PropVistiorPtr(new PropVistiorImpl<T>(ptr));
        JZProperty *prop = JZPropertyManager::instance()->create(qMetaTypeId<T>(),name);
        prop->setValue(QVariant::fromValue<T>(*ptr));
        addProp(prop, vistor, parent);
        return prop;
    }
    JZProperty *addPropFile(QString name,QString *ptr, QString filter, JZProperty *parent = nullptr);
    JZProperty *addPropDir(QString name, QString *ptr, JZProperty *parent = nullptr);

    template<class T>
    JZProperty *addPropIntEnum(QString name, T *ptr, QList<int> valueList, QStringList textList, JZProperty *parent = nullptr)
    {
        PropVistiorPtr vistor = PropVistiorPtr(new PropVistiorEnumImpl<T>(ptr));
        JZProperty *prop = new JZPropertyIntEnum(name, valueList, textList);
        prop->setValue((int)(*ptr));
        addProp(prop, vistor, parent);
        return prop;
    }

    void addProp(JZProperty *prop, PropVistiorPtr vistor, JZProperty *parent = nullptr);

    void dataToUi();  //更新数据
    void uiToData();

protected slots:
    void onValueChanged(JZProperty *pin, const QVariant &value);

protected:
    void clear();

    JZPropertyBrowser *m_browser;
    QMap<JZProperty*, PropVistiorPtr> m_propMap;
    bool m_editing;
};

#endif
